/** ============================================================================================== **/
/* 										BUILD MAPPA E WIDGET								  	 	*/	
/** ============================================================================================== **/

BootApplication.controller("BuildMapCtrl",
	  [ "$scope", '$rootScope', "log", "$translate", "$compile", "olMapsInst", "olBuildService", "olControlService", "olFormatService", "olFeatureService", 
	    "DialogService", "ngeoDecorateInteraction", "olInteractionService", "configuration", "olLayerService", "olStyleService", "ngeoDecorateLayer", 
	    "TemplatesPopupSrv",/*"NotificheSrv",*/ "$q","$http",
function($scope, $rootScope, log, $translate, $compile, olMapsInst, olBuildService, olControlService, olFormatService, olFeatureService, DialogService, 
		 ngeoDecorateInteraction, olInteractionService, configuration, olLayerService, olStyleService, ngeoDecorateLayer, TemplatesPopupSrv,/*NotificheSrv,*/
		 $q,$http) {

 /*******************************************************************************************/
 /*  								 INIZIALIZZAZIONE MAPPA								    */
 /*******************************************************************************************/
	/**
	 * Costruisce la mappa dalle configurazioni fornite in ingresso.
	 */
	var olMaps = olBuildService.buildMapToOptions($scope.olMapConfiguration);
	/**
	 * Add instance to scope
	 */
	$scope.olMap = olMaps.getMap2DInstance();
	$rootScope.olMap = olMaps.getMap2DInstance();

 /*******************************************************************************************/
 /*  							 INIZIALIZZAZIONE WIDGET MAPPA							    */
 /*******************************************************************************************/

	/**
	 * Aggiunge alla mappa la lista dei controlli non di default abilitati, configurati in base alle options fornite.
	 * Un controllo è un widget visibile con un elemento DOM in una posizione fissa sullo schermo.
	 *
	 * NOTA:
	 * 	Per default i widget sono già integrati alla mappa quando la si crea.
	 *  Questi vengono integrati in un secondo momento perchè vi è la necessita di aggiungere un comportamento particolare
	 *  al click.
	 *  L'integrazione avviene aggiungendo nell'html della pagina la direttiva "ngeo-control" nel seguente modo :
	 *
	 *   (code)
	 *   	<div id="zoom" ngeo-control="ctrl.zoomControl" ngeo-control-map="ctrl.olMap"></div>
	 *   (code)
	 *
	 * La direttiva "ngeo-control" si occupa lei di aggiungere il controllo di openlayers alla mappa indicata nell' attributo
	 * "ngeo-control-map" della direttiva stessa.
	 * La componente Html del controllo di openlayers viene disegnata direttamente nel DIV che chiama la direttiva "ngeo".
	 *
	 */

	/** Layer Tree Widget **/
	if($scope.olMap.getOptions().isEnableLayersTree()) {
		/**
		 * Recupero dallo scope i dati utili al build dell'albero dei layer.
		 *
		 *  - "treeControl": controllo di openlayers per "Mostrare e nascondere l'albero".
		 */
		$scope.treeControl = $scope.olTreeConfiguration.getTreeControl();
	}// close if isEnableLayersTree

	/** Geolocation Widget **/
	if($scope.olMap.getOptions().isEnableGeolocation()) {
		/**
		 * ol.Geolocation :
		 *  L'API Geolocation viene utilizzato per individuare la posizione di un utente.
		 *  Per ricevere la notifica di cambiamenti di posizione, registrare un listener per l'evento di modifica generica sull'istanza di
		 *  ol.Geolocation.
		 *
		 * NOTA: Il costruttore ol.Geolocation è stato esteso aggiungendo alle proprietà già previste la proprietà "geolocateZoom".
		 */
		$scope.geolocation = olControlService.createolGeolocation($scope.olMap.getOptions());

		/**
		 * Ritorna il layer vector appositamente configurato per la visualizzazione su mappa
		 * della posizione geolocalizzata dell'utente.
		 */
		var geoVector = olLayerService.createLayerVectorToGeolocate($scope.olMap);

		/**
		 * Imposta il layer come da renderizzare in cima gli altri livelli su una mappa. La mappa non gestirà questo strato nella sua collezione
		 * strati, e il callback in ol.Map#forEachLayerAtPixel riceverà null come valore.
		 * Ciò è utile per i livelli temporanei. Per rimuovere uno strato non gestito dalla mappa, utilizzare #setMap(null).
		 */
		geoVector.setMap($scope.olMap);

		/**
		 * update the HTML page and feature coordinate when the position changes.
		 */
		$scope.geolocation.on('change', function() {
		    /** The current position of the device reported in the current projection. **/
			var position = $scope.geolocation.getPosition();

			/** disegno la feature della posizione **/
			var positionFeature =  new ol.Feature({
				  	/** The default geometry for the feature. ol.geom.Geometry **/
					geometry: olFormatService.olCoordinateToPoint($scope.geolocation.getPosition(), configuration.getParam("ol.geom.GeometryLayout").XY),
					/** **/
					name: 'Posizione Utente',
					/** number | string | undefined **/
					id: "geolocateMe"
				});

			  /** svuoto il layer temporaneo dalle feature **/
			  geoVector.getSource().clear();
			  /** aggiungo la nuova feature **/
			  geoVector.getSource().addFeature(positionFeature);

			  /**
			   * Genero una transizione animata durante l'aggiornamento del centro della mappa.
			   */
			  var pan = ol.animation.pan({
				    /** The duration of the animation in milliseconds. Default is 1000. **/
				    duration: 2000,
				    /** The location to start panning from, typically map.getView().getCenter(). **/
				    source: $scope.olMap.getView().getCenter()
			  });
			  /**
			   * Aggiungo l'animazione che deve essere richiamata prima del rendering(prima di aggiornare la visualizzazione della mappa).
			   */
			  $scope.olMap.beforeRender(pan);
			  /** centro la mappa sulle coordinate della posizione utente **/
			  $scope.olMap.getView().setCenter($scope.geolocation.getPosition());
			  /** zoom alla coordinata **/
			  $scope.olMap.getView().setZoom($scope.geolocation.getGeolocateZoom());
		});
		/**
		 * handle geolocation error.
		 */
		$scope.geolocation.on('error', function(error) {
		   /**
		    */
		   DialogService.showErrorAlertApplication($translate.instant('OpenLayers.olGeolocation.errorGeolocate'));
		});

		/**
		 * Aggiungo il controllo di openlayer che, se premuto, viene individuata la posizione di un utente.
		 */
		$scope.geolocationControl = olControlService.createGeolocationControl($scope.olMap.getOptions());

		/**
		 * Gestione del click sul pulsante "geolocationControl", attiva e disattiva il tracking della posizione dell'utente
		 */
		$scope.clickGeolocationControl = function (){
			if($scope.openGeoControl){
				// Abilito il tracking.
				$scope.geolocation.setTracking(true);
			}else{
				/** svuoto il layer dalle feature **/
				geoVector.getSource().clear();

				// Disabilito il tracking.
				$scope.geolocation.setTracking(false);
			}
		};
	}// close if isEnableGeolocation


	/** Misura della lunghezza Widget **/
	if($scope.olMap.getOptions().isEnableMeasureLength()) {

		/**
		 * Aggiungo il controllo di openlayer che, se premuto, viene attivato lo strumento per disegnare su mappa
		 * e misurare la lunghezza dell'arco tracciato.
		 */
		$scope.measureLengthControl = olControlService.createMeasureLengthControl($scope.olMap.getOptions());

		/**
		 * Ritorna lo strumento di disegno appositamente configurato per tracciare linee su mappa.
		 * "ngeo" mette a disposizione un'Interaction dedicata per misurare la lunghezza.
		 */
		$scope.measureLengthInteraction = olInteractionService.createNgeoMeasureLengthInteraction();

		/**
		 * NOTA "ngeoDecorateInteraction":
		 *   Fornisce una funzione che aggiunge una proprietà "active" (usando Object.defineProperty) ad una interaction, rendendo possibile
		 *   l'uso di ng-model per attivare / disattivare interazioni.
		 */
		ngeoDecorateInteraction($scope.measureLengthInteraction);

		/**
		 * Aggiungo l'interaction alla mappa
		 */
		$scope.olMap.addInteraction($scope.measureLengthInteraction);
	}// close if isEnableMeasureLength

	/** Misura dell'area Widget **/
	if($scope.olMap.getOptions().isEnableMeasureArea()) {

		/**
		 * Aggiungo il controllo di openlayer che, se premuto, viene attivato lo strumento per disegnare su mappa
		 * e misurare la grandezza della superficie.
		 */
		$scope.measureAreaControl = olControlService.createMeasureAreaControl($scope.olMap.getOptions());

		/**
		 * Ritorna lo strumento di disegno appositamente configurato per tracciare l'area su mappa.
		 * "ngeo" mette a disposizione un'Interaction dedicata per misurare la superficie.
		 */
		$scope.measureAreaInteraction = olInteractionService.createNgeoMeasureAreaInteraction();

		/**
		 * NOTA "ngeoDecorateInteraction":
		 *   Fornisce una funzione che aggiunge una proprietà "active" (usando Object.defineProperty) ad una interaction, rendendo possibile
		 *   l'uso di ng-model per attivare / disattivare interazioni.
		 */
		ngeoDecorateInteraction($scope.measureAreaInteraction);

		/**
		 * Aggiungo l'interaction alla mappa
		 */
		$scope.olMap.addInteraction($scope.measureAreaInteraction);
	}// close if isEnableMeasureArea

	/** Misura azimut Widget **/
	if($scope.olMap.getOptions().isEnableMeasureAzimut()) {

		/**
		 * Aggiungo il controllo di openlayer che, se premuto, viene attivato lo strumento per disegnare su mappa un cerchio e misurarne la
		 * larghezza del diametro e l'angolo.
		 */
		$scope.measureAzimutControl = olControlService.createMeasureAzimutControl($scope.olMap.getOptions());

		/**
		 * Ritorna lo strumento di disegno appositamente configurato per tracciare l'area su mappa.
		 * "ngeo" mette a disposizione un'Interaction dedicata per misurare la superficie.
		 */
		$scope.measureAzimutInteraction = olInteractionService.createNgeoMeasureAzimutInteraction();

		/**
		 * NOTA "ngeoDecorateInteraction":
		 *   Fornisce una funzione che aggiunge una proprietà "active" (usando Object.defineProperty) ad una interaction, rendendo possibile
		 *   l'uso di ng-model per attivare / disattivare interazioni.
		 */
		ngeoDecorateInteraction($scope.measureAzimutInteraction);

		/**
		 * Aggiungo l'interaction alla mappa
		 */
		$scope.olMap.addInteraction($scope.measureAzimutInteraction);
    }// close if isEnableMeasureAzimut

 /*******************************************************************************************/
 /*   						 	   GESTIONE ALBERO DEI LAYER							    */
 /*******************************************************************************************/

	/** Layer Tree Widget **/
	if($scope.olMap.getOptions().isEnableLayersTree()) {

		/**
		 * Triggered when an node is selected
		 * 
		 * @param {@link Object} node, selected Array the current selection 
		 * @param {@link Object} event, the event (if any) that triggered this select_node
		 */
		function selectNodeCB(event, obj) {
			/**
			 * Controllo se ci sono nodi selezionati
			 */
			if(obj != null && obj.node != null){
				/** Controllo se è stato selezionato il nodo della categoria o i figli */
				if($.isNumeric(obj.node.id))
					/** E' stato selezionato il nodo della categoria quindi devo ciclare i nodi figli e renderli selezionati */
					angular.forEach(obj.node.children, function(value, key) {       
						selectTreeLayer(value);
					});
				else
				  /** E' stato selezionato un nodo figlio lo seleziono */
				  selectTreeLayer(obj.node.id);
			}// close selected
		};// close selectNodeCB
		
		/**
		 * Triggered when an node is deselected
		 * 
		 * @param {@link Object} node 
		 * @param {@link Array} selected, the current selection
		 * @param {@link Object} event, the event (if any) that triggered this deselect_node
		 */	  	
		function deselectNodeCB(event, obj) {
			/**
			 * Controllo se ci sono nodi deselezionati
			 */
			if(obj != null && obj.node != null){
				/** Controllo se è stato deselezionato il nodo della categoria o i figli */
				if($.isNumeric(obj.node.id))
					/** E' stato selezionato il nodo della categoria quindi devo ciclare i nodi figli e renderli deselezionati */
					angular.forEach(obj.node.children, function(value, key) {       
						deselectTreeLayer(value);
					});
				else
				  /** E' stato selezionato un nodo figlio lo deseleziono */
				  deselectTreeLayer(obj.node.id);
			}// close selected
		};
		
		/**
		 * Recupero dallo scope i dati utili al build dell'albero dei layer.
		 *
		 *  - "treeConfig": l'oggetto di configurazione del JsTree
		 *  - "treeData": l'array con gli elementi della struttura
		 */
		$scope.treeConfig = $scope.olTreeConfiguration.getTreeConfig();
		$scope.treeData = $scope.olTreeConfiguration.getTreeData();
		$scope.treeLayer = $scope.olTreeConfiguration.getTreeLayers();
		$scope.treeStyles = $scope.olTreeConfiguration.getTreeStyles();
		$scope.treeEventsObj = { 'select_node': selectNodeCB, 'deselect_node': deselectNodeCB };

		/** Ciclo i layer dell'albero la prima volta di modo da aggiungere alla mappa quelli già resi visibili */
		angular.forEach($scope.treeLayer, function(layer, key) {       
			if(layer.visible) selectTreeLayer(layer.codice);
		});
			    
		/**
		 * Aggiunge alla mappa il layer selezionato dall'albero
		 */
		function selectTreeLayer(value){
			
			var addedLay = new Array(); 
			
			/* Recupero l'anagrafica layer associata al codice layer selezionato */
			var layerSel = $scope.treeLayer[value];
			
			if(angular.equals(layerSel.layerType, configuration.getParam("ol.LayerType").VECTOR)) {
				
				/* Get ol.layer.Vector */
				var olLayer = olLayerService.createOlLayerVectorFromTree(
						$scope.olMap, layerSel, $translate.use(), $scope.treeStyles, $scope.olMap.getOptions().getSourceProjection(), $scope.olMap.getOptions().getDestProjection());
			    
				/* add */
				addedLay.push(olLayer);
				
				/* Controllo se il layer selezionato ne ha configurato uno complementare */ 
				if(layerSel.complLayer != null && layerSel.complLayer != "" ){
					
					/* Recupero l'anagrafica layer associata al codice layer complementare */
					var layerCompl = $scope.treeLayer[layerSel.complLayer];
					
					/* Get ol.layer.Vector */
					var olLayerCompl = olLayerService.createOlLayerVectorFromTree(
							$scope.olMap, layerCompl, $translate.use(), $scope.treeStyles, $scope.olMap.getOptions().getSourceProjection(), $scope.olMap.getOptions().getDestProjection());
					
					/* add */
					addedLay.push(olLayerCompl);
				}
			}// close vector
			
			if(angular.equals(layerSel.layerType, configuration.getParam("ol.LayerType").IMAGE_WMS)){
				
				/* Get ol.layer.Image */
				var olLayer = olLayerService.createOlLayerImageWMSFromTree(layerSel, $translate.use());
			    
				/* add */
				addedLay.push(olLayer);
			}// close image wms
			
			if(angular.equals(layerSel.layerType, configuration.getParam("ol.LayerType").TILE_WMS)){
				
				/* Get ol.layer.Tile */
				var olLayer = olLayerService.createOlLayerTileWMSFromTree(layerSel, $translate.use());
			    
				/* add */
				addedLay.push(olLayer);
			}// close tile wms
			
			/* add layers map */
			$scope.olMap.addLayers(addedLay);	
		}// close selectTreeLayer
		
		/**
		 * Rimuove dalla mappa il layer deselezionato dall'albero
		 */
		function deselectTreeLayer(value){
			/* Recupero l'anagrafica layer assciata al codice layer deselezionato */
			var layerSel = $scope.treeLayer[value];
			
			if(angular.equals(layerSel.layerType, configuration.getParam("ol.LayerType").VECTOR)) {
				
				/* Controllo se il layer deselezionato ne ha configurato uno complementare */ 
				if(layerSel.complLayer != null && layerSel.complLayer != "" ){
					
					/* Recupero l'anagrafica layer associata al codice layer complementare */
					var olLayer = $scope.olMap.getLayerByName(layerSel.complLayer);
					
					/*
					 * Removes the given layer from the map.
					 */
					if(angular.isDefined(olLayer) && olLayer != null) $scope.olMap.removeLayer(olLayer);
				}
			}// close vector
			
			/* Recupero l'anagrafica layer assciata al codice layer deselezionato */
			var olLayer = $scope.olMap.getLayerByName(layerSel.codice);
			
			/*
			 * Removes the given layer from the map.
			 */
			if(angular.isDefined(olLayer) && olLayer != null) $scope.olMap.removeLayer(olLayer);
		}// close deselectTreeLayer

		/**
		 * Abilito l'opzione per cui le modifiche del modello (treeData) si rifletteranno nella struttura.
		 */
		$scope.ignoreModelChanges = function (){ return true; }

		/**
		 * Gestione filro di ricerca dell'albero dei layer.
		 */
		$scope.ngSearchTreeLayer = function (){
			/** get testo digitato **/
			var value = $scope.ngTxtSearchTreeLayer;

			// $('#tree2').jstree(true); -->> get an existing instance (will not create new instance)

			/** utilizzato per cancellare l'ultima ricerca (rimuove le classi e mostra tutti i nodi di filtraggio è ON) **/
			$scope.treeInstance.jstree(true).clear_search();
			/** avvio ricerca **/
			$scope.treeInstance.jstree(true).search(value);
		};

		/**
		 * Gestione reset filtro ricerca layer
		 */
		$scope.ngClearSearchTreeLayer = function (){
			/** svuoto il campo di ricerca **/
		    $scope.ngTxtSearchTreeLayer = "";
		    /** utilizzato per cancellare l'ultima ricerca (rimuove le classi e mostra tutti i nodi di filtraggio è ON) **/
		    $scope.treeInstance.jstree(true).clear_search();
		};
	}//close if isEnableLayersTree


 /** ======================================================================================== **/
 /*  								INTERACTION HIGHLIGHTS FEATURE							   */
 /** ======================================================================================== **/

	/**
	 * Ritorna lo strumento che gestisce l'highlights dei dati vettoriali.
	 */
	$scope.highlightsInteraction = new ol.interaction.Select({
		/* Identificativo interaction **/
		id: null,
		/*
		 * A list of layers from which features should be selected. Alternatively, a filter function can be provided.
		 * The function will be called for each layer in the map and should return true for layers that you want to be selectable.
		 * If the option is absent, all visible layers will be considered selectable.
		 */
		layers: null,
		/*
		 * Un valore booleano che determina se il comportamento di default dovrebbe essere la selezione singola delle feature
		 * o anche più di una. Il valore predefinito è falso i.e select singola.
		 */
		multi: false,
		/*
		 * Una funzione che prende un ol.MapBrowserEvent e restituisce un valore booleano che indica se l'evento deve essere gestito.
		 * Questo è l'evento da scatenare per la selezione.
		 * Cliccando su una feature la seleziona rimuovendo eventuali altre feature dalla selezione.
		 * Facendo clic al di fuori di una feature le rimuove tutte dalla selezione.
		 */
		condition: ol.events.condition.pointerMove,
		/*
		 * Style for the selected features (those in the FeatureOverlay).
		 */
		style: function (feature){
			var style = null;
			
			var layer = $scope.highlightsInteraction.getLayer(feature);
			
			if(layer != undefined && layer != null) style = layer.getStyleFunction()(feature);
			
			return style;
		}
	});

	/** true if the interaction is active, false otherwise. **/
	$scope.highlightsInteraction.setActive(true);
	/**
	 * Add the given interaction to the map.
	 */
	$scope.olMap.addInteraction($scope.highlightsInteraction);

 /** ======================================================================================== **/
 /*  								 INTERACTION SELECT FEATURE								   */
 /** ======================================================================================== **/

	/**
	 * Ritorna lo strumento che gestisce la selezione dei dati vettoriali.
	 */
	$scope.selectInteraction = new ol.interaction.Select({
			/* Identificativo interaction **/
		 	id: null,
	 		/*
		 	 * A list of layers from which features should be selected. Alternatively, a filter function can be provided.
		 	 * The function will be called for each layer in the map and should return true for layers that you want to be selectable.
		 	 * If the option is absent, all visible layers will be considered selectable.
		 	 */
			layers: null,
			/*
			 * Un valore booleano che determina se il comportamento di default dovrebbe essere la selezione singola delle feature
			 * o anche più di una. Il valore predefinito è falso i.e select singola.
			 */
			multi: false,
			/*
			 * Una funzione che prende un ol.MapBrowserEvent e restituisce un valore booleano che indica se l'evento deve essere gestito.
			 * Questo è l'evento da scatenare per la selezione.
			 * Cliccando su una feature la seleziona rimuovendo eventuali altre feature dalla selezione.
			 * Facendo clic al di fuori di una feature le rimuove tutte dalla selezione.
			 */
			condition: ol.events.condition.singleClick,
			/*
			 * Style for the selected features (those in the FeatureOverlay).
			 */
			style: function (feature){
				var style = null;
				
				var layer = $scope.selectInteraction.getLayer(feature);
				
				if(layer != undefined && layer != null) style = layer.getStyleFunction()(feature);

				return style;
			}
	});

	/** true if the interaction is active, false otherwise. **/
	$scope.selectInteraction.setActive(true);

	/**
	 * Add the given interaction to the map.
	 */
	$scope.olMap.addInteraction($scope.selectInteraction);

	
	/**
	 * Listner per cambio cursore a movimento mouse
	 */
	$scope.olMap.on("pointermove", function (event) {
	    var mouseCoordInMapPixels = [event.originalEvent.offsetX, event.originalEvent.offsetY];
	    //detect feature at mouse coords
	    var hit = $scope.olMap.forEachFeatureAtPixel(mouseCoordInMapPixels, function (feature, layer) {
	        return true;
	    });
	    
	    var _feature = $scope.olMap.forEachFeatureAtPixel(mouseCoordInMapPixels, function (feature, layer) {
	    	return feature;
	    });

	    var _layer = $scope.olMap.forEachFeatureAtPixel(mouseCoordInMapPixels, function (feature, layer) {
	    	return layer;
	    });

	    var target = $scope.olMap.getTarget();
	    var jTarget = typeof target === "string" ? $("#"+target) : $(target);

	    $scope.monitoraggioOverlay.getSource().clear();
	    if (hit) {
	    	_layerMonitoringMezzo = configuration.getParam("Constants").layersName["MONITORAGGIO_TPL_MAPPA"]
	    	_layerStop            = configuration.getParam("Constants").layersName["MONITORAGGIO_TPL_STOP"]
	    	if(_layer 
	    	&& _feature
	    	&& _layerMonitoringMezzo == _layer.getName()
	    	){
	    		_overlayFeature = new ol.Feature({geometry: new ol.geom.Point(_feature.getGeometry().getCoordinates())});
	    		
	    		_overlayFeature.setProperties(_feature.getProperties());
	    		
	    		$scope.monitoraggioOverlay.getSource().addFeature(_overlayFeature);
	    		
	    		_backgroundColor = "#005E91";
	    		_textColor       = "#FFF";

                $scope.monitoraggioMezzoElement.css('background-color', _backgroundColor);
                $scope.monitoraggioMezzoElement.css('color'           , _textColor      );
                $scope.monitoraggioMezzoElement.css('border-color'    , _textColor      );
                
                _msg = _feature.getProperties().trip;
	    		if(_feature.getProperties().delay)
	    			_msg +=  " " + _feature.getProperties().delay + " min.";
    			
	    		$scope.monitoraggioMezzoElement.find("#spanCorsaPopup").html(_msg);
	    		
                $scope.monitoraggioMezzoOverlay.setPosition(olFeatureService.getCentroidGeometry(_feature.getGeometry()));
	    		
                $scope.monitoraggioStopOverlay.setPosition(undefined);
//POPUP STOP ON MOUSE OVER	    	
	    	}else if(_layer 
	    	     && _feature
	    	     && _layerStop == _layer.getName()
	    	){
	    		
	    		if(_feature.getProperties()){
	    			_name = _feature.getProperties().name;
	    			if(_name){
	    				$scope.monitoraggioStopElement.find("#titleMonitoraggioContent").html(_name);
	    				$scope.monitoraggioStopOverlay.setPosition(olFeatureService.getCentroidGeometry(_feature.getGeometry()));
	    			}
	    		}
	    		$scope.monitoraggioMezzoOverlay.setPosition(undefined);
	    	}
	        jTarget.css("cursor", "pointer");
	    } else {
	        jTarget.css("cursor", "");
	        $scope.monitoraggioStopOverlay .setPosition(undefined);
	        $scope.monitoraggioMezzoOverlay.setPosition(undefined);
	    }
	});
	/**
	 * Listner in select event
	 */
	$scope.selectInteraction.on('select', function(e) {
		console.log("click1");
		if(e.selected.length != 0){
			/* recupero la feature selezionata */
			var fea = e.selected[0];
			/* */
			var myLayer = $scope.selectInteraction.getLayer(fea);
			/* Apre la popup della feature selezionata. */
			//if(angular.isDefined(fea) && fea != null && angular.isDefined(myLayer) && myLayer != null) $scope.openPopup(fea, false, myLayer.getName());
			/* Apre la popup della feature selezionata. */
			if(angular.isDefined(fea) && fea != null && angular.isDefined(myLayer) && myLayer != null){
		        $scope.openPopup(fea, false, myLayer.getName());
			 }
			/* */
			$scope.selectInteraction.getFeatures().clear(true);
		}
	});
	$scope.removeNotificaSinottico = function(_id,_isAnomalia, _isEvento, _isAllarme) {
		log.debug("removeNotificaSinottico");
		$scope.closePopup();
		
		_element = new Object();
		if (_isAnomalia) { 
			_element.codiceAnomalia=_id;
			MonitoraggioTplSrv.removeAnomalia(_element, $scope.olMap);
			delete $rootScope.anomalieAttive[_id];
		} else if (_isEvento) {
			_element.codiceEvento=_id;
			MonitoraggioTplSrv.removeEvento(_element, $scope.olMap);
			delete $rootScope.eventiAttivi[_id];
		} else if (_isAllarme) {
			_element.codiceAllarme=_id;
			MonitoraggioTplSrv.removeAllarme(_element, $scope.olMap);
			delete $rootScope.allarmiAttivi[_id];
		}
	}
	/**
	 * Nasconde la popup se aperta, e deseleziona l'eventuale feature selezionata.
	 */
	$scope.closePopup = function() {
		/**
		 * Set the position for this overlay. If the position is undefined the overlay is hidden.
		 */
		$scope.overlay.setPosition(undefined);

		/** set undefined value */
		$scope.overlay.layerName = undefined;

		/** Elimino le feature eventualmente selezionate. */
		if( $scope.highlightsInteraction != null ) $scope.highlightsInteraction.getFeatures().clear(true);
		/** Elimino le feature eventualmente selezionate. */
		if( $scope.selectInteraction != null ) 	   $scope.selectInteraction.getFeatures().clear(true);

		return false;
	}// close closePopup

	/**
	 * Apre la popup della feature selezionata.
	 *
	 * @param {@link ol.Feature} fea, A vector object for geographic features with a geometry and other attribute properties
	 * @param {@link Boolean} centerOn, True o false a seconda se si vuole zoomare all'estensione del layer dopo l'apertura della popup
	 * @param {@link String} layerName, codice layer per recuperare la popup
	 */
	$scope.openPopup = function (fea, centerOn, layerName){
		/* e stata selezionata una feature nascondo la popup corrente. If the position is undefined the overlay is hidden */
		$scope.overlay.setPosition(undefined);
		/* set undefined */
		$scope.overlay.layerName = undefined;
		/* svuoto la variabile di scope dove mantengo l'informazione dell'anagrafica della feature selezionata */
		$scope.properties = null;

		/*
		 * Dopodicchè in base alla geometria, cerco di determinare un punto centrale alla stessa da assegnare all'overlay
		 * come la posizione in cui se deve aprire.
		 */
		var coordinates = olFeatureService.getCentroidGeometry(fea.getGeometry());
		/* Se non rieso a determinarle imposto undefined */
		if (coordinates == null) coordinates = undefined;
			
		/* recupero le proprieta della feature, le aggiungo allo scope di modo che siano accesibili dal template della popup **/
		$scope.properties = fea.getProperties();

		/* recupero il template della popup associato a questo nome layer */
		var template = TemplatesPopupSrv[layerName](fea);

		/* scrivo all'interno del template della popup, il template dell'anagrafica */
		$scope.element.find(".popup-content").html(template);

		/* compile code angular */
		$compile($scope.element)($scope);

		/* set code layer associato alla feature di cui si sta aprendo la popup */
		$scope.overlay.layerName = layerName;

		/* mostro la popup settando la coordinate della posizione dell'overlay */
		$scope.overlay.setPosition(coordinates);
		
		if(centerOn) {
			/* Ottenere l'estensione delle features. */
	    	var extent = fea.getGeometry();

	    	/* Adatta la forma geometrica data o misura in base alla data dimensione mappa e di confine. **/
	    	$scope.olMap.getView().fit(extent, $scope.olMap.getSize()[0] == 0 ? [500, 500] : $scope.olMap.getSize(), {"maxZoom": 14});
		}
	}// close openPopup

	/**
	 * Aggiorna le proprietà della popup, verificando che ci sia una popup visibile di quel layer e che si riferisca alla feature
	 * con id "properties.id".
	 *
	 * @param {@link ol.Feature} fea, feature selezionata
	 * @param {@link String} layerName, codice layer per recuperara la popup
	 */
	$scope.refreshPopup = function (fea, layerName){

		if($scope.overlay.getPosition() != undefined && $scope.overlay.layerName != undefined && $scope.overlay.layerName == layerName && $scope.properties.id == fea.getProperties().id){
			/* recupero le proprieta della feature, le aggiungo allo scope di modo che siano accesibili dal template della popup **/
			$scope.properties = fea.getProperties();

			/* recupero il template della popup associato a questo nome layer */
			var template = TemplatesPopupSrv[layerName](fea);

			/* scrivo all'interno del template della popup, il template dell'anagrafica */
			$scope.element.find(".popup-content").html(template);

			/* compile code angular */
			$compile($scope.element)($scope);
		}
	}// close refreshPopup


 /** ======================================================================================== **/
 /*  								 		POPUP FEATURE									   */
 /** ======================================================================================== **/

	/* popup template */
	$scope.element = angular.element(
						"<div class='ol-popup' ng-cloak translate-cloak>" +
							"<span class='ol-popup-closer' ng-click='closePopup()'></span>" +
			 			 	"<div class='popup-content' ng-cloak translate-cloak ></div>" +
			 			"</div>" );

	/**
	 * Un elemento da visualizzare sulla mappa e collegata a una singola posizione sulla mappa.
	 * Come ol.control.Control, overlay sono i widget visibili. A differenza dei controlli, non sono in una posizione fissa sullo schermo,
	 * ma sono legati a coordinate geografiche, così lo scorrimento della mappa muoverà l'overlay ma non un controllo.
	 */
	$scope.overlay = new ol.Overlay({
		id: "overlayAllEntity",
		/**
		 * The overlay element.
		 */
        element: $scope.element[0],
        /**
         * Defines how the overlay is actually positioned with respect to its position property.
         * Possible values are 'bottom-left', 'bottom-center', 'bottom-right', 'center-left', 'center-center', 'center-right', 'top-left',
         * 'top-center', and 'top-right'. Default is 'top-left'.
         */
        positioning: 'top-center',
        /**
         * Whether event propagation to the map viewport should be stopped. Default is true.
         * If true the overlay is placed in the same container as that of the controls (CSS class name ol-overlaycontainer-stopevent);
         * if false it is placed in the container with CSS class name ol-overlaycontainer.
         */
        stopEvent: true,
        /**
         * if set to true the map is panned when calling setPosition, so that the overlay is entirely visible in the current viewport.
         * The default is false.
         */
        autoPan: true,
        /**
         * The options used to create a ol.animation.pan animation. This animation is only used when autoPan is enabled.
         * By default the default options for ol.animation.pan are used. If set to null the panning is not animated.
         */
        autoPanAnimation: {
           /** The duration of the animation in milliseconds. Default is 1000. **/
           duration: 250,
           /** Maintain a constant speed over time.**/
           easing: ol.easing.linear
        },
        /**
         * The margin (in pixels) between the overlay and the borders of the map when autopanning. The default is 20.
         */
        autoPanMargin: 20
     });

	/** Add the given overlay to the map.**/
	$scope.olMap.addOverlay($scope.overlay);


 /*******************************************************************************************/
 /*  						 INIZIALIZZAZIONE VARIABILI DI SCOPE						    */
 /*******************************************************************************************/
	
	/**
	 * Per default la variabile che determina se aggiungere o meno il cssClass "full-tools" ai controlli è false.
	 */
	$scope.ngFulltools = false;
	
	/**
	 * Questa funzione gestisce la possibilita di passare da una modalità di zoom all'altra.
	 * In particolare quando in ingresso viene fornita la stringa:
	 *
	 *   - DEFAULT: Viene attivato il controllo con 2 pulsanti, uno per lo zoom in e una per lo zoom out.
	 *   - SLIDER:  Viene attivato il controllo con 2 pulsanti, uno per lo zoom in e una per lo zoom out e lo slider centrale per spostarsi direttamente
	 * 			    ad un certo livello di zoom.
	 */
	$scope.changeInOutSliderZoom = function (modalita, target){
		if(modalita == 'SLIDER'){

			/** Valorizzo a true la variabile che determina l'aggiunta del cssClass "full-tools" ai controlli. */
			$scope.ngFulltools = true;

			/** Attivo un controllo mostrandolo sulla mappa **/
			angular.element("#" + target + " .ol-overlaycontainer-stopevent").addClass("full-tools");
			angular.element("#" + target + " .ol-zoomslider").show();
		}else
			if(modalita == 'DEFAULT'){
				/** Valorizzo a false la variabile che determina la rimozione del cssClass "full-tools" ai controlli. */
				$scope.ngFulltools = false;

				/** Disattivare un controllo significa nasconderlo dalla mappa **/
				angular.element("#" + target + " .ol-zoomslider").hide();
				angular.element("#" + target + " .ol-overlaycontainer-stopevent").removeClass("full-tools");
			}
	};// close changeInOutSliderZoom

	/** Se i controllo "zoomSlider" e "zoom" sono entrambi attivi abilito la modalità per cui si possa passre da un controllo all'altro **/
	if($scope.olMap.getOptions().isEnableZoomSlider()) {

		if($scope.olMap.getOptions().isEnableZoom()) {
			/**
			 * Per default è attivo "ol.control.Zoom"
			 */
			$scope.changeInOutSliderZoom('SLIDER', $scope.olMap.getOptions().getTargetMap());
		}else
		   /** Aggiungo il cssClass di modo che lo slider si veda correttamente **/
		   angular.element("#" + target + " .ol-overlaycontainer-stopevent").addClass("full-tools");
	}
	
 /*******************************************************************************************/
 /*  						END: INIZIALIZZAZIONE VARIABILI DI SCOPE					    */
 /*******************************************************************************************/
	
 /*******************************************************************************************/
 /*  						     FUNZIONI POPUP MONITORAGGIO TPL					  	    */
 /*******************************************************************************************/
		

	  $scope.monitoraggioStopElement = angular.element("<div id=\"divFermataPopup\" class=\"monitoraggioPopup\">"
			                                          + "<span id='titleMonitoraggioContent'></span>" 
			                                          + "</div>" 
			                                          );
	  
	  $scope.monitoraggioStopOverlay = new ol.Overlay({id         : "overlayStopMonitoring"
		                                              ,element    : $scope.monitoraggioStopElement[0]
		                                              ,positioning: 'bottom-left'
		                                              ,stopEvent  : false
		                                              ,autoPan    : false
	                                                  });


	  $scope.monitoraggioMezzoElement = angular.element("<div id=\"divMezzoPopup\" class=\"monitoraggioPopup\">"
                                                     +    "<span id='spanCorsaPopup'></span>"
                                                     + "<div>"
	                                                   );
	  
	  $scope.monitoraggioMezzoOverlay = new ol.Overlay({id         : "overlayMezzopMonitoring"
		                                               ,element    : $scope.monitoraggioMezzoElement[0]
	                                                   ,positioning: 'bottom-left'
		                                               ,stopEvent  : false
		                                               ,autoPan    : false
	                                                   });
	  
	 
      $scope.monitoraggioOverlay = new ol.layer.Vector({source: new ol.source.Vector()
                                                       ,style : function (feature, resolution) {
                                                                    return [MonitoraggioTplSrv.styleMezzoOverlay(feature.getProperties())];
                                                                                                }
                                                       ,name : configuration.getParam("Constants").layersName["MONITORAGGIO_TPL_MAPPA"]
                                                       ,zIndex:100
                                                        });
 /*******************************************************************************************/
 /*  						    END: FUNZIONI POPUP MONITORAGGIO TPL				  	    */
 /*******************************************************************************************/
}]);
